/**********************************************************************************
 * Code license:  GNU General Public License v3                                   *
 * Main page:     https://code.google.com/p/library-cross-platform/               *
 * Issue tracker: https://code.google.com/p/library-cross-platform/issues/list    *
***********************************************************************************/

package library.util;

import java.util.*;
import java.lang.reflect.*;
import library.classloader.*;

@SuppressWarnings({ "rawtypes", "unchecked" })
public abstract class EventHandler {
  protected        String              nextEvent;
  protected        ClassLoadSingleton  classload;
  protected        Hashtable           loadedClasses;
  protected        Hashtable           regsteredEvnents;
  protected        EventHandler        parent;
  
  protected EventHandler() {
    classload        = new ClassLoadSingleton();
    loadedClasses    = new Hashtable();
    regsteredEvnents = new Hashtable();
  }
  
  public EventHandler(EventHandler parent) {
    this();
    setParent(parent);
  }
  
  public static EventHandler getNewInstance(Class lClass) throws IllegalAccessException, InstantiationException {
    java.lang.String name = lClass.getCanonicalName();
    EventHandler handler = (EventHandler)lClass.newInstance();
    handler.registerClass(name, handler);
    return handler;    
  }
  
  public void setParent(EventHandler parent) {
    this.parent = parent;
  }
  
  public EventHandler getParent() {
    return parent;
  }
  
  public void setNextEvent(String event) throws IllegalEventException {
    if(regsteredEvnents.get(event) == null)
     throw new IllegalEventException();
	  
    nextEvent = event;
  }

  public final String getNextEvent() {
    return nextEvent;
  }

  public EventListener getEventListener(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
    return (EventListener)getObject(className);
  }
  
  public EventListener getEventListener(String eventClassName, Object notused) {
    EventListener eventListener = null;
    try {
      eventListener = getEventListener(eventClassName);
    } catch(ClassNotFoundException e ) {
      e.printStackTrace(); 
    } catch( InstantiationException e) {
      e.printStackTrace();
    } catch(IllegalAccessException e) {
      e.printStackTrace();
    } catch(InvocationTargetException e) {
      e.printStackTrace();
    } catch(NoSuchMethodException e ) {
      e.printStackTrace();
    } catch(SecurityException e) {
      e.printStackTrace();
   }
   return eventListener;
  }
  
  public void registerClass(String className, Object obj) {
    classload.registerClass(className, obj);
    loadedClasses.put(className, obj);
  }


  public Object getObject(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
    Object result = loadedClasses.get(className);
    if(result != null)
     return result;
    else {
      result = classload.getClass(className);
      loadedClasses.put(className, result);
    }
    return result;
  }

  public Object getObject(String className, Object notused) {
    Object retObject = null;
    try {
      retObject = getObject(className);
    } catch(ClassNotFoundException e ) {
      e.printStackTrace(); 
    } catch( InstantiationException e) {
      e.printStackTrace();
    } catch(IllegalAccessException e) {
      e.printStackTrace();
    } catch(InvocationTargetException e) {
      e.printStackTrace();
    } catch(NoSuchMethodException e ) {
      e.printStackTrace();
    } catch(SecurityException e) {
      e.printStackTrace();
    }
    return retObject;
  }

  public void registrateEvent(String newEvent, String className) {
    regsteredEvnents.put(newEvent, className);
  }
  
  public void removeEvent(String event) {
    java.lang.String className = getEventClassName(event);
    regsteredEvnents.remove(event);
    classload.removeClass(className);
    loadedClasses.remove(className);    
  }

  protected String getEventClassName(String event) {
    return (String)regsteredEvnents.get(event);
  }

  public abstract boolean startEventStates() throws InvocationTargetException, NoSuchMethodException, SecurityException;
}
